package main.math;

public class UtilFunctions {

	public static double combination(int n, int k) throws Exception {
		return fatorial(n)/fatorial(k)*fatorial(n-k);
	}

	public static double fatorial(int i) throws Exception {
		if (i<0) {
			throw new Exception("Factorial argument cannot be below 0!");
		}
		else if (i==1 || i==0) {
			return 1;
		}
		else {
			return i*fatorial(i-1);
		}
	}	

	public static double[] matrixMultiplication(double[] matrix1, double[] matrix2) {
		double[] result = new double[matrix1.length];
		for (int i = 0; i < result.length; i++) {
			result[i] = matrix1[i]*matrix2[i];
		}
		return result;
	}

	public static double euclidianNorm(double[] matrix) {
		double result = 0;
		for (int i = 0; i < matrix.length; i++) {
			result += Math.pow(Math.abs(matrix[i]),2);
		}
		return Math.sqrt(result);
	}

	public static double[][] matrixMultiplication(double[] d, double[][] hessian) throws Exception {		
		if (d.length == hessian.length) {
			double[][] result = new double[d.length][hessian.length];
			for  (int i=0; i<=d.length; i++) {
				for (int j=0; j<=hessian.length; j++) {
					result[i][j] = d[i]*hessian[i][j]; 
				}
			}
			return result;
		}
		else {
			throw new Exception("Matrixes sizes don't match!");
		}
	}

	public static double[][] matrixSum(double[] d, double[][] hessian) throws Exception {		
		if (d.length == hessian.length && d.length == hessian[0].length) {
			for  (int i=0; i<=d.length; i++) {
				hessian[i][i]+=d[i];
			}
			return hessian;
		}
		else {
			throw new Exception("Matrixes sizes don't match!");
		}
	}

	//TODO saber como resolve esse sistema linear direito
	public static double[] solveLinearSystem(double[][] matrix1, double[] matrix2) {
		double[] result = new double[matrix1.length];
		for (int i=0; i<=matrix1.length; i++) {
			result[i] = matrix2[i]/matrix1[i][i];
		}
		return null;
	}

	public static double[] subVectors(double[] vector1, double[] vector2) throws Exception {
		if (vector1.length != vector2.length) {
			double[] result = new double[vector1.length];
			for (int i = 0; i < result.length; i++) {
				result[i] = vector1[i]-vector2[i];
			} 
			return result;
		}
		else {
			throw new Exception("Vector sizes don't match!");
		}		
	}
	
	public static double[] addVectors(double[] vector1,	double[] vector2) throws Exception {
		if (vector1.length != vector2.length) {
			double[] result = new double[vector1.length];
			for (int i = 0; i < result.length; i++) {
				result[i] = vector1[i]+vector2[i];
			} 
			return result;
		}
		else {
			throw new Exception("Vector sizes don't match!");
		}	
	}

	public static double[] multiplyVectorByScalar(double[] vector, double scalar) {
		double[] result = new double[vector.length];
		for (int i=0; i<vector.length; i++) {
			result[i] = vector[i]*scalar;
		}
		return result;
	}	
}